package edu.towson.greenteam.table;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import edu.towson.greenteam.Consts;
import edu.towson.greenteam.CustomerQueue;
import edu.towson.greenteam.Iterator;
import edu.towson.greenteam.Collection;
import edu.towson.greenteam.order.Order;

/* Tables observes Orders queue:
 * 1.  When an order is removed/dequeued, Tables checks to see if all orders
 *     for the given Table ID have been prepared.  If all orders have been prepared,
 *     notify the CustomerQueue. 
 * 2.  Observed by CustomerQueue
 */


public class Tables extends Observable implements Observer, Collection<Table>
{
    private ArrayList<Observer> observers;
	private CustomerQueue customersQueue;
	public static ArrayList<Table> currentTables;
	private int lastID = 0;
	private int maxTables=Consts.MAX_TABLES;
	
	public Tables() {
    	observers = new ArrayList<Observer>(); 
		currentTables = new ArrayList<Table>();
	}

	
	public boolean add(int numseats, boolean occupied, int pin) {
		
		if (currentTables.size() < maxTables)
		{
			int newid = lastID++;
			Table newTable = new Table(newid, numseats, occupied, pin);
			return currentTables.add(newTable);
		}
		return false;
	}

	@Override
	public boolean add(Table e) {
		boolean r=false;
		if (currentTables.size() <= maxTables)
		{
			int newid = lastID+1;
			Table newTable = new Table(newid);
			if (newTable != null){
				newTable.setNumSeats(e.getNumSeats());
				newTable.setOccupied(e.isOccupied());
				newTable.setPin(e.getPin());
				r = currentTables.add(newTable);
			}
		}
		return r;
	}

	@Override
	public boolean update(Table e) {
		
		Table oldTable = currentTables.get(e.getId());
		if (oldTable != null){
			oldTable.setNumSeats(e.getNumSeats());
			oldTable.setOccupied(e.isOccupied());
			oldTable.setPin(e.getPin());
			return true;
		}
		return false;
	}

	@Override
	public boolean contains(Table e) {
		return currentTables.contains(e);
	}

	@Override
	public boolean remove(Table e) {
		return currentTables.remove(e);
	}

	@Override
	public boolean isEmpty() {
		return currentTables.isEmpty();
	}

	@Override
	public int size() {
		return currentTables.size();
	}
	
	public Table get(int i) {
		return currentTables.get(i);
	}
	
	public void setMaxTables(int mx){
		maxTables = mx;
	}
	
	/****Iterators****/
	/*****************/
	@SuppressWarnings("unchecked")
	public Iterator<Table> getItr() {
		return (Iterator<Table>)currentTables.iterator();
	}
	
	public Iterator<Table> createTblNotOccupiedItr() {
		return new TableNotOccupiedItr(this);
		
	}
	
	
	/************************************************************************
	 * Methods for being an OBSERVER (i.e. Tables observes Orders)
	 ***********************************************************************/
	@Override
	public void update(Observable arg0, Object arg) {
		String changedClass = arg0.getClass().getCanonicalName();
		if (changedClass == Consts.ORDERS) {
            Order orderJustServed = (Order) arg;
            Table tableJustServed = orderJustServed.getTable();
            ArrayList<Order> allTableOrders = tableJustServed.getAllTablesOrders();
            boolean allServed = true;
            for (Order order : allTableOrders) {
                if (order.isServed()==false) {
                    allServed = false;
                    break;
                }
            }
            // If all orders for the table just served have been served...
            if (allServed == true) {
                setChanged();
                notifyObservers(tableJustServed); // notify customerQueue
            }
		}
	}
	
	/************************************************************************
	 * Methods for being OBSERVABLE (i.e. Tables observed by CustomerQueue)
	 ***********************************************************************/
	@Override
    public void notifyObservers() {
    	
    }
    @Override 
    public void addObserver(Observer o) { 
        this.observers.add(o); 
    }
	@Override
    public void notifyObservers(Object  arg) {
    	for (int i=0; i<observers.size(); i++) {
    		Observer o = (Observer) observers.get(i);
    		o.update(this, arg);
    	}		
    }

	public void setCustomerQueue(CustomerQueue c) {
		this.customersQueue = c;
	}
	
	@Override
	public String toString() {
		String sReturn = new String();
		// Display orders 
		for (int i=0; i<currentTables.size(); i++)
		{
			Table tbl = (Table) currentTables.get(i);
			String fsTable;
			String sOccupied = "No";
			if (tbl.isOccupied() == true)
				sOccupied = "Yes";
			fsTable = String.format("Id: %d   Seats: %d   Occupied: %s",
                    tbl.getId(), tbl.getNumSeats(), sOccupied);
			sReturn = sReturn.concat(fsTable + Consts.newline);
		}
		return sReturn;
	}
}
